package com.orange.ui.launcher;

import com.orange.content.SceneBundle;
import com.orange.engine.Engine;
import com.orange.engine.options.EngineOptions;
import com.orange.engine.options.PixelPerfectEngineOptions;
import com.orange.entity.scene.ISceneLauncher;
import com.orange.entity.scene.Scene;
import com.orange.entity.scene.group.SceneGroup;
import com.orange.ui.launcher.modifier.DestroyEntityModifierListener;
import com.orange.ui.launcher.modifier.EnterEntityModifierListener;
import com.orange.ui.launcher.modifier.ExitEntityModifierListener;
import com.orange.util.ReflectionUtils;

public abstract class GameLauncher extends BaseGameLauncher implements ISceneLauncher{

	// ===========================================================
	// 虚拟方法
	// ===========================================================

	protected abstract PixelPerfectEngineOptions onCreatePixelPerfectEngineOptions();

	protected abstract void onLoadResources();

	protected abstract void onLoadComplete();
	
	// ===========================================================
	// 变量
	// ===========================================================

	private SceneGroup mSceneGroup;

	private PixelPerfectEngineOptions mPixelPerfectEngineOptions;
	
	// ===========================================================
	// 继承方法
	// ===========================================================

	
	public void Create() {
		// TODO Auto-generated method stub
		this.mPixelPerfectEngineOptions = this.onCreatePixelPerfectEngineOptions();
		super.Create();
	}

	
	public EngineOptions onCreateEngineOptions() {
		// TODO Auto-generated method stub
		return this.mPixelPerfectEngineOptions.createEngineOptions();
	}

	
	public void onCreateResources(final OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
		// TODO Auto-generated method stub
		this.onLoadResources();
		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}

	
	public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
		// TODO Auto-generated method stub
		pOnCreateSceneCallback.onCreateSceneFinished(new SceneGroup());
	}

	
	public void onPopulateScene(SceneGroup pSceneGroup, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
		// TODO Auto-generated method stub
		this.mSceneGroup = pSceneGroup;
		pOnPopulateSceneCallback.onPopulateSceneFinished();
		this.onPrepareLoadComplete();
		this.onLoadComplete();
	}

	protected void onPrepareLoadComplete() {

	}

	// ===========================================================
	// 场景操作
	// ===========================================================

	/**
	 * 开启一个场景具体请参考
	 * {@link GameLauncher#startSceneForResult(Class, SceneBundle, int)}
	 * 
	 * @param pSceneCls
	 * @return
	 */
	
	public Scene startScene(Class<? extends Scene> pSceneCls) {
		return startScene(pSceneCls, null);
	}

	/**
	 * 开启一个场景具体请参考
	 * {@link GameLauncher#startSceneForResult(Class, SceneBundle, int)}
	 * 
	 * @param pSceneCls
	 * @param bundle
	 * @return
	 */
	
	public Scene startScene(Class<? extends Scene> pSceneCls, SceneBundle bundle) {
		return this.startSceneForResult(pSceneCls, bundle, -1);
	}

	/**
	 * 开启一个场景具体请参考
	 * {@link GameLauncher#startSceneForResult(Class, SceneBundle, int)}
	 * 
	 * @param pSceneCls
	 * @param requestCode
	 * @return
	 */
	
	public Scene startSceneForResult(Class<? extends Scene> pSceneCls, int requestCode) {
		return this.startSceneForResult(pSceneCls, null, -1);
	}

	/**
	 * 开启一个场景
	 * 
	 * @param pSceneCls
	 *            场景类
	 * @param bundle
	 *            数据
	 * @param requestCode
	 *            请求代码，用于数据返回标志，不能为负数
	 * @return
	 */
	
	public Scene startSceneForResult(Class<? extends Scene> pSceneCls, SceneBundle bundle, int requestCode) {
		// 开启新场景
		Scene gameScene = ReflectionUtils.newInstance(pSceneCls);
		Class<?>[] parameterTypes = { ISceneLauncher.class, Engine.class, SceneBundle.class, int.class };
		Object[] argParam = { this, this.getEngine(), bundle, requestCode };
		ReflectionUtils.invokeMethod(gameScene, "init", parameterTypes, argParam);
		this.mSceneGroup.attachScene(gameScene);
		gameScene.onSceneResume();
		// 停止底下场景
		int sceneCount = this.mSceneGroup.getSceneCount();
		// 第一个场景播放动画
		if (sceneCount > 1) {
			Scene lastScene = this.mSceneGroup.getSceneByIndex(sceneCount - 2);

			new EnterEntityModifierListener(this.mSceneGroup, gameScene, lastScene.getEnterEntityModifier());

			if (lastScene != null && !lastScene.isScenePause()) {
				lastScene.onScenePause();
				new ExitEntityModifierListener(this.mSceneGroup, lastScene, lastScene.getExitEntityModifier());
			}
			// 其余场景只做停止处理
			if (sceneCount > 2) {
				for (int i = sceneCount - 3; i >= 0; i--) {
					Scene bottomScene = this.mSceneGroup.getSceneByIndex(i);
					if (bottomScene != null && !bottomScene.isScenePause()) {
						bottomScene.onScenePause();
						new ExitEntityModifierListener(this.mSceneGroup, bottomScene, null);
					}
				}
			}
		} else {
			//modifier为null时，不播放动画，这里实现效果为直接显示
			new EnterEntityModifierListener(this.mSceneGroup, gameScene, null);
		}
		return gameScene;
	}

	/**
	 * 停止一个场景
	 * 
	 * @param pScene
	 */
	
	public void finishScene(Scene pScene) {
		int sceneCount = this.mSceneGroup.getSceneCount();
		if (sceneCount > 1) {
			Scene lastScene = this.mSceneGroup.getLastScene();
			for (int i = sceneCount - 1; i >= 0; i--) {
				Scene bottomScene = this.mSceneGroup.getSceneByIndex(i);
				if (bottomScene != null && bottomScene != lastScene) {
					lastScene = bottomScene;
					break;
				}
			}
			// 关闭当前场景
			pScene.onScenePause();
			pScene.onSceneDestroy();
			new DestroyEntityModifierListener(this.mSceneGroup, pScene, pScene.getExitEntityModifier());
			
			// 重新开启底下场景
			if (lastScene != null && lastScene.isScenePause()) {
				lastScene.onSceneResult(pScene.getRequestCode(), pScene.getResultCode(), pScene.getResultBundle());
				lastScene.onSceneResume();
				new EnterEntityModifierListener(this.mSceneGroup, lastScene, pScene.getEnterEntityModifier());
			}
		} else {
			this.finishGame();
		}
	}


	// ===========================================================
	// 系统事件映射
	// ===========================================================

	
	public synchronized void Resume() {
		// TODO Auto-generated method stub
		super.Resume();
		if (this.mSceneGroup != null) {
			int sceneCount = this.mSceneGroup.getSceneCount();
			if (sceneCount > 0) {
				Scene lastScene = this.mSceneGroup.getLastScene();
				if (lastScene != null) {
					if (lastScene.isScenePause()) {
						lastScene.onSceneResume();
					}
				}
			}
		}
	}

	
	public void Pause() {
		// TODO Auto-generated method stub
		super.Pause();
		if (this.mSceneGroup != null) {
			int sceneCount = this.mSceneGroup.getSceneCount();
			if (sceneCount > 0) {
				Scene lastScene = this.mSceneGroup.getLastScene();
				if (lastScene != null) {
					if (!lastScene.isScenePause()) {
						lastScene.onScenePause();
					}
				}
			}
		}
	}

	
	public void Destroy() {
		// TODO Auto-generated method stub
		super.Destroy();
		if (this.mSceneGroup != null) {
			int sceneCount = this.mSceneGroup.getSceneCount();
			if (sceneCount > 0) {
				Scene lastScene = this.mSceneGroup.getLastScene();
				if (lastScene != null) {
					lastScene.onSceneDestroy();
				}
			}
		}
	}

	
	public Boolean onKeyDown(int keyCode) {
		// TODO Auto-generated method stub
		if (this.mSceneGroup != null) {
			Scene lastScene = this.mSceneGroup.getLastScene();
			if (lastScene != null) {
				return lastScene.onKeyDown(keyCode);
			} else {
				return super.onKeyDown(keyCode);
			}
		} else {
			return super.onKeyDown(keyCode);
		}
	}

	public Boolean onKeyUp(int keyCode) {
		// TODO Auto-generated method stub
		if (this.mSceneGroup != null) {
			Scene lastScene = this.mSceneGroup.getLastScene();
			if (lastScene != null) {
				return lastScene.onKeyUp(keyCode);
			} else {
				return super.onKeyUp(keyCode);
			}
		} else {
			return super.onKeyUp(keyCode);
		}
	}
	
	public void finishGame() {
		if (this.onPrepareFinish()) {
			super.finishGame();
		}
	}

	/**
	 * 准备关闭，在此可以做对话框能功能
	 * 
	 * @return 返回true则继续执行finish，返回false终止执行
	 */
	protected boolean onPrepareFinish() {
		return true;
	}

	public void finish() {
		
	}

	public SceneGroup getSceneGroup() {
		return mSceneGroup;
	}
}
